/* $RCSFile: ADNDynList.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/DynEntities/ADNDynList.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:33  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using CrmSdk;
using System.Globalization;

namespace AddonNice.CRMWrapper
{
	public class ADNDynList : DynEntity
	{
        protected class Ftor: DFactor
        {
            public Ftor() : base(CrmStr.list)
            {}

            public override Type DynType
            { get { return typeof(ADNDynList); } }

            public override string DynTypename
            {   get{ return CrmStr.list;}}

            public override DynEntity Build()
            {   return new ADNDynList();}

            public override DynEntity Build(CRMWrapperBase w, InternalDynamicEntity dEntity, PropertyDescriptorCollection wproperties)
            {   return new ADNDynList(w, dEntity, wproperties, null);}

            public override DynEntity Build(CRMWrapperBase w, string PrimaryFieldValue)
            {   return new ADNDynList(w,PrimaryFieldValue);}

            public override DynEntity Build(CRMWrapperBase w,Guid PrimaryKeyValue)
            {   return new ADNDynList(w,PrimaryKeyValue);}
        }

        static ADNDynList(){new Ftor();} 

        public override bool HasOwningBusinessUnitProperty
        {
            get{   return true;}
        }

        public ADNDynList(): base()
		{}
        
        public ADNDynList(CRMWrapperBase w, string PrimaryFiedlValue)
			: base(w,CrmStr.list)
		{
            if ( PrimaryFiedlValue != string.Empty )
                listname    =   PrimaryFiedlValue;
		}

		public ADNDynList(CRMWrapperBase w, Guid CrmId)
			: base(w,CrmStr.list, CrmId)
		{}

		public ADNDynList(CRMWrapperBase w, InternalDynamicEntity e)
			: base(w,CrmStr.list,e,null,null)
		{}

		public ADNDynList(CRMWrapperBase w, InternalDynamicEntity e,PropertyDescriptorCollection prop,InternalColumnSet s)
			: base(w,CrmStr.list,e,prop,s)
		{}

        public ADNDynList(ResetWrapperHandler fn, string PrimaryFiedlValue)
			: base(fn,CrmStr.list)
		{
            if ( PrimaryFiedlValue != string.Empty )
                listname    =   PrimaryFiedlValue;
		}

		public ADNDynList(ResetWrapperHandler fn, Guid CrmId)
			: base(fn,CrmStr.list, CrmId)
		{}

		public ADNDynList(ResetWrapperHandler fn, InternalDynamicEntity e)
			: base(fn,CrmStr.list,e,null,null)
		{}

		public ADNDynList(ResetWrapperHandler fn, InternalDynamicEntity e,PropertyDescriptorCollection prop,InternalColumnSet s)
			: base(fn,CrmStr.list,e,prop,s)
		{}
		
        /// <summary>
		/// Crm Key
		/// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public Guid listid
		{
			get
			{
				return KeyPropertyValue(CrmStr.listid);
			}
			set
			{
				AddKeyProperty(CrmStr.listid, value);
			}
		}

        protected override void SetCrmIdProperty(Guid crmId)
        {
           if ( !dicProperty.ContainsKey(CrmStr.listid) || KeyPropertyValue(CrmStr.listid) != crmId )
                listid   =   crmId;
        }
        

        public override Guid PrimaryKeyGuidValue
        {
           get
           {
                return listid;
           }
           set
           {
               listid    =   value;
           }
        }

        [CrmDynAttribute(CrmStr.list)]
        public string listname
        {
            get
            {
                return StringPropertyValue(CrmStr.listname);
            }
            set
            {
                AddStringProperty(CrmStr.listname,value);
            }
        }
        
        /// <summary>
        /// Gets the exchange rate for the currency associated with the list with respect to the base currency. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public decimal exchangerate
        {
            get
            {
                return DecimalPropertyValue(CrmStr.exchangerate);
            }
            set
            {
                AddDecimalProperty(CrmStr.exchangerate,value);
            }
        }

        /// <summary>
        /// Gets and sets the ID of the currency associated with the list. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public Guid transactioncurrencyid
        {
            get
            {
                return LookupPropertyValue(CrmStr.transactioncurrencyid);
            }
            set
            {
                AddLookupProperty(CrmStr.transactioncurrencyid,CrmStr.transactioncurrency,value);
            }
        }

        public string transactioncurrencyName
        {
            get
            {
                return LookupPropertyName(CrmStr.transactioncurrencyid);
            }
        }

        /// <summary>
        /// Gets or sets the cost of the marketing list. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public decimal cost
        {
            get
            {
                if ( dicProperty.ContainsKey(CrmStr.cost) )
                    return MoneyPropertyValue(CrmStr.cost);
                return 0;
            }
            set
            {
                AddMoneyProperty(CrmStr.cost,value);
            }
        }

        /// <summary>
        /// Gets the base currency equivalent of the rounding option amount for the price list. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public decimal cost_base
        {
            get
            {
                if ( dicProperty.ContainsKey(CrmStr.cost_base) )
                    return MoneyPropertyValue(CrmStr.cost_base);
                return 0;
            }
        }

        /// <summary>
        /// Contains the description of the list. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public string description 
        {
            get
            {
                return StringPropertyValue(CrmStr.description);
            }
            set
            {
                AddStringProperty(CrmStr.description,value);
            }
        }
        
        /// <summary>
        /// Gets or sets the type of entity contained in this list 
        /// Account
        /// Contact
        /// Lead
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public int createdfromcode 
        {
            get
            {
                return PicklistPropertyIntValue(CrmStr.createdfromcode);
            }
            set
            {
                AddPicklistProperty(CrmStr.createdfromcode,value);
            }
        }

        public string createdfromcodeLabel
        {
            get
            {
                return PicklistPropertyLabelValue(CrmStr.createdfromcode);
            }
        }

        /// <summary>
        ///  Gets or sets the reason why the marketing list was created. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public string purpose 
        {
            get
            {
                return StringPropertyValue(CrmStr.purpose);
            }
            set
            {
                AddStringProperty(CrmStr.purpose,value);
            }
        }
 
        /// <summary>
        /// Gets or sets the source of the marketing list. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public string source 
        {
            get
            {
                return StringPropertyValue(CrmStr.source);
            }
            set
            {
                AddStringProperty(CrmStr.source,value);
            }
        }

        /// <summary>
        ///  Gets or sets a value that indicates whether to send marketing material to list members that prohibits sending of marketing material. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public bool donotsendonoptout
        {
            get 
            {
                return BooleanPropertyValue(CrmStr.donotsendonoptout);
            }
            set
            {
                AddBooleanProperty(CrmStr.donotsendonoptout,value);
            }
        }

        /// <summary>
        ///  Gets or sets a value that indicates whether to ignore inactive marketing list members during propagation/execution. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public bool ignoreinactivelistmembers
        {
            get 
            {
                return BooleanPropertyValue(CrmStr.ignoreinactivelistmembers);
            }
            set
            {
                AddBooleanProperty(CrmStr.ignoreinactivelistmembers,value);
            }
        }

 
        /// <summary>
        ///  Gets or sets a value that indicates whether the marketing list is locked. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public bool lockstatus
        {
            get 
            {
                return BooleanPropertyValue(CrmStr.lockstatus);
            }
            set
            {
                AddBooleanProperty(CrmStr.lockstatus,value);
            }
        }
 
        /// <summary>
        /// Gets the date and time when the list was last used in a campaign, to create activities, or to create opportunities. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public string lastusedon
        {
            get
            {
                return DateTimePropertyValue(CrmStr.lastusedon);
            }
            set
            {
                AddDateTimeProperty(CrmStr.lastusedon,value);
            }
        }

        /// <summary>
        /// Gets the total number of members that can be stored in the marketing list. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public int membercount
        {
            get
            {
                if ( ContainsKey(CrmStr.membercount) )
                    return NumberPropertyValue(CrmStr.membercount);
                return 0;
            }
            set
            {
                AddNumberProperty(CrmStr.membercount,value);
            }
        }

        public enum ListType : int
        {
            Account =   1,// Specifies a list of accounts. 
            Contact =   2, // Specifies a list of contacts. 
            Lead    =   4 //Specifies a list of leads. 
        }

        public ListType MemberType
        {
            get
            {
                return (ListType)membertype;
            }
        }

        public string MemberTypename
        {
            get
            {
                switch ( membertype )
                {
                    case 1:
                    return CrmStr.account;
                    case 2:
                    return CrmStr.contact;
                    case 4:
                    return CrmStr.lead;
                    default:
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// GuidKey name for the member entity
        /// </summary>
        public string MemberLinkKey
        {
            get
            {
                switch ( membertype )
                {
                    case 1:
                    return CrmStr.accountid;
                    case 2:
                    return CrmStr.contactid;
                    case 4:
                    return CrmStr.leadid;
                    default:
                    return string.Empty;
                }
            }
        }

        /// <summary>
        /// Gets or sets the type of the members that can be stored in the marketing list: account, contact, or lead. 
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public int membertype
        {
            get
            {
                if ( ContainsKey(CrmStr.membertype) )
                    return NumberPropertyValue(CrmStr.membertype);
                return 0;
            }
            set
            {
                AddNumberProperty(CrmStr.membertype,value);
            }
        }
        
        /// <summary>
        /// virtual because on 'detail' records it is only a uniqueidentifier property
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public Guid owningbusinessunit
        {
            get
            {
                return LookupPropertyValue(CrmStr.owningbusinessunit);
            }
            set
            {
                AddLookupProperty(CrmStr.owningbusinessunit,CrmStr.businessunit,value);
            }
        }

        public string owningbusinessunitName
        {
            get
            {
                return LookupPropertyName(CrmStr.owningbusinessunit);
            }
        }

        /// <summary>
        /// Owner for this object
        /// </summary>
        [CrmDynAttribute(CrmStr.list)]
        public override Guid ownerid
        {
            get
            {
                if ( ContainsKey(CrmStr.ownerid) )
                    return OwnerPropertyValue(CrmStr.ownerid);
                return Guid.Empty;
            }
            set
            {
                AddOwnerProperty(CrmStr.ownerid,CrmStr.systemuser,value);
            }
        }

        #region utilities

        /// <summary>
        /// Add a new member to the list
        /// </summary>
        public Guid AddMemberList(ADNDynCustomer dynTarget,bool isAdmin)
        {
            return wrapper.Util.AddMemberList(this,dynTarget,isAdmin);
        }

    
        // delegate to be applied to all list members
        public delegate bool ListMemberDelegate(ADNDynCustomer dynCust);


        List<ADNDynCustomer> _List                                  =   null;

        public List<ADNDynCustomer> ForceGetMembers(ResetWrapperHandler fn)
        {
            _List   =   null;
            return GetMembers(fn);
        }

        public List<ADNDynCustomer> GetMembers(ResetWrapperHandler fn)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList GetMembers BEG source: {0}, membertype: {1}",listname,MemberTypename),CRMDynTraceSwitch.Sw.Info);
            if ( _List != null )
            {
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine(string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList GetMembers END existing count: {0}",_List.Count),CRMDynTraceSwitch.Sw.Info);
                return _List;
            }
            int count                                               =   0;
            _List                                                   =   new List<ADNDynCustomer>();
            try
            {
                string targetEntity                                 =   MemberTypename;
                
                GenericDynQueryMultiple<DynEntity> allEntQuery      =   new GenericDynQueryMultiple<DynEntity>(wrapper,fn,targetEntity);
                InternalQueryExpression qe                          =   new InternalQueryExpression();
                qe.EntityName                                       =   targetEntity;
                InternalAllColumns RequestCols                      =   new InternalAllColumns();
                
                // link from customer entity to listmember
                InternalLinkEntity le                               =   new InternalLinkEntity();
                le.LinkFromEntityName                               =   targetEntity;
                le.LinkFromAttributeName                            =   MemberLinkKey;
                le.LinkToEntityName                                 =   CrmStr.listmember;
                le.LinkToAttributeName                              =   CrmStr.entityid;

                // link from listmember to list
                InternalLinkEntity le2                              =   new InternalLinkEntity();
                le2.LinkFromEntityName                              =   CrmStr.listmember;
                le2.LinkFromAttributeName                           =   CrmStr.listid;
                le2.LinkToEntityName                                =   CrmStr.list;
                le2.LinkToAttributeName                             =   CrmStr.listid;

                
                InternalFilterExpression fi                         =   new InternalFilterExpression();
                // condition for listid
                InternalConditionExpression ex                      =   new InternalConditionExpression();
                ex.AttributeName                                    =   CrmStr.listid;
                ex.Operator                                         =   InternalConditionOperator.Equal;
                ex.Values                                           =   new string[]{listid.ToString()};

                //add condition to linkentity
                le2.LinkCriteria                                    =   fi;
                fi.Conditions                                       =   new InternalConditionExpression[]{ex};

                // chain linkentity2 to linkentity
                le.LinkEntities                                     =   new InternalLinkEntity[]{le2};

                //add linkentities to Query Expression 
                qe.LinkEntities                                     =   new InternalLinkEntity[]{le};
                qe.ColumnSet                                        =   RequestCols;
                
                
                InternalBusinessEntityCollection allEnt             =   allEntQuery.adminRetrieve(qe);
                PropertyDescriptorCollection _columnDescriptors     =   null;
                EntityConfig ListMemberTConfig                      =   new EntityConfig(wrapper,targetEntity);
                // Transform them in DynEntities and insert them in dynEntList
                if ( allEntQuery.RetrievedCount > 0 )
                {
                    // Transform them in DynEntities and insert them in dynEntList
                    wrapper.Util.ExecForEachDynamicEntity(allEnt,
                        delegate(InternalDynamicEntity de)
                        {
                            DynEntity ob                            =   DynEntity.CreateFromDynamicEntity(wrapper,fn,de,_columnDescriptors);
                            ob.EntityMData                          =   ListMemberTConfig.entityMetaData;
                            _columnDescriptors                      =   ob.PropertyDescriptorCollection;
                            _List.Add(ob as ADNDynCustomer);
                            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList GetMembers found entity: {0}", ob.PrimaryFieldStringValue),CRMDynTraceSwitch.Sw.Info);
                            return true; // continue
                        });
                }
            }
            catch (Exception ex)
            {
                string msg          =   string.Format("[E]ADNDynList GetMembers ex : {0}", ex);
                if (CRMDynTraceSwitch.Sw.TraceError || CRMDynTraceSwitch.Sw.TraceError)
                    Trace.WriteLine( msg,(CRMDynTraceSwitch.Sw.TraceError) ? CRMDynTraceSwitch.Sw.Info : CRMDynTraceSwitch.Sw.Info);
                throw ex;
            }

            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList GetMembers END found: {0}", count),CRMDynTraceSwitch.Sw.Info);
            return _List;
        }
        
        /// <summary>
        /// Apply this delegate to all list members
        /// </summary>
        public void ExecForEachMember(ResetWrapperHandler fn,ListMemberDelegate delg)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList ExecForEachMember BEG source: {0}, membertype: {1}",listname,MemberTypename),CRMDynTraceSwitch.Sw.Info);
            int count                                               =   0;
            try
            {
                List<ADNDynCustomer> List                           =   GetMembers(fn);
                count                                               =   List.Count;
                for (int i = 0; i < count; i++)
                {
                    ADNDynCustomer m                                =   List[i];
                    string PrimaryFieldStringValue                  =   m.PrimaryFieldStringValue;
                    if (CRMDynTraceSwitch.Sw.TraceVerbose)
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList ExecForEachMember entity: {0}, i: {1}/{2}",PrimaryFieldStringValue, i+1,count), CRMDynTraceSwitch.Sw.Info);
                    if ( !delg(m) )
                    {
                        if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList ExecForEachMember breaking loop on {0}.",PrimaryFieldStringValue),CRMDynTraceSwitch.Sw.Info);
                        break;
                    }
                    if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList ExecForEachMember done {0}.",PrimaryFieldStringValue),CRMDynTraceSwitch.Sw.Info);
                }
            }
            catch (Exception ex)
            {
                string msg          =   string.Format("[E]ADNDynList ExecForEachMember ex : {0}", ex);
                if (CRMDynTraceSwitch.Sw.TraceError || CRMDynTraceSwitch.Sw.TraceError)
                    Trace.WriteLine( msg,(CRMDynTraceSwitch.Sw.TraceError) ? CRMDynTraceSwitch.Sw.Info : CRMDynTraceSwitch.Sw.Info);
                throw ex;
            }

            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynList ExecForEachMember END found: {0}", count),CRMDynTraceSwitch.Sw.Info);
        }
        
        #endregion utilities
    }
}
